package com.vclee.fast.integration.imserver;

import io.netty.channel.Channel;
import io.netty.channel.ChannelInitializer;
import io.netty.channel.ChannelPipeline;
import io.netty.handler.codec.http.HttpObjectAggregator;
import io.netty.handler.codec.http.HttpServerCodec;
import io.netty.handler.ssl.SslContext;
import io.netty.handler.ssl.SslContextBuilder;
import io.netty.handler.stream.ChunkedWriteHandler;
import io.netty.handler.timeout.IdleStateHandler;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.stereotype.Component;

import javax.net.ssl.KeyManagerFactory;
import java.io.InputStream;
import java.security.KeyStore;
import java.util.Objects;
import java.util.concurrent.TimeUnit;

@Component
public class ImChannelInitializer extends ChannelInitializer<Channel> {

    @Value("${custom.im-ssl:false}")
    private boolean ssl; // 设置为 true表示启用ssl false表示不启用ssl 默认为false

    /**
     *  进行设置心跳检测
     *  服务端10秒钟都没接收到客户端的消息，则会触发写空闲，会给客户端发送ping消息
     *  如果能收到pong消息则表示在线。
     *  如果在发送ping消息5秒内都收不到pong消息。则表示用户已经断线了。
     *  此时会触发读空闲，我们在这里关闭该链接。
     *  allIdleTime为0表示不触发读写空闲
     */
    @Override
    protected void initChannel(Channel channel) throws Exception {
        ChannelPipeline pipeline = channel.pipeline();
        if(ssl){
            pipeline.addLast(buildSslContext().newHandler(channel.alloc()));  // 添加ssl协议即用wss调用
        }
        pipeline.addLast("http-codec", new HttpServerCodec()); // Http消息编码解码
        pipeline.addLast("aggregator", new HttpObjectAggregator(512 * 1024)); // Http消息组装(聚合器，很重要)
        pipeline.addLast("http-chunked", new ChunkedWriteHandler()); // WebSocket通信支持
        pipeline.addLast(new IdleStateHandler(15, 10, 0, TimeUnit.SECONDS)); // WebSocket通信支持
        pipeline.addLast("handler", new ImChannelHandler()); //自己处理的handler
    }

    private SslContext buildSslContext() throws Exception {
        char[] passArray = "whrpabk0".toCharArray();
        KeyStore ks = KeyStore.getInstance("JKS");
        InputStream inputStream = ImChannelInitializer.class.getClassLoader().getResourceAsStream("keystore.jks");
        ks.load(inputStream, passArray);
        KeyManagerFactory kmf = KeyManagerFactory.getInstance(KeyManagerFactory.getDefaultAlgorithm());
        kmf.init(ks, passArray);
        Objects.requireNonNull(inputStream).close();
        return SslContextBuilder.forServer(kmf).build();
    }
}
